﻿using System;
using System.Security.Cryptography;

namespace LinkedInApi
{
    public class AccessToken
    {
        internal string Token { get; private set; }
        public DateTime ExpireDate { get; private set; }

        public bool IsValid
        {
            get
            {
                return DateTime.Now <= this.ExpireDate;
            }
        }

        public TimeSpan TimeLeft
        {
            get
            {
                return this.ExpireDate - DateTime.Now;
            }
        }

        internal AccessToken(string token, int secondsRemaining)
        {
            this.Token = token;
            this.ExpireDate = DateTime.Now.AddSeconds(secondsRemaining);
        }

        public byte[] Encrypt(string salt, ILogger logger = null)
        {
            try
            {
                return ProtectedData.Protect(this.GetData(), AccessToken.GetEntropy(salt), DataProtectionScope.CurrentUser);
            }
            catch (Exception e)
            {
                if (logger != null)
                    logger.Log("AccessToken", "Encrypt error: {0}", e.ToString());
                return null;
            }
        }

        public static AccessToken Decrypt(byte[] data, string salt, ILogger logger = null)
        {
            try
            {
                var originalString = System.Text.Encoding.UTF8.GetString(ProtectedData.Unprotect(data, AccessToken.GetEntropy(salt), DataProtectionScope.CurrentUser));
                var originalData = originalString.Split(new string[] {"%%%"}, StringSplitOptions.None);

                return new AccessToken(originalData[0], 0) 
                { 
                    ExpireDate = DateTime.FromBinary(long.Parse(originalData[1])) 
                };
                
            }
            catch (Exception e)
            {
                if (logger != null)
                    logger.Log("AccessToken", "Decrypt error: {0}", e.ToString());
                return null;
            }
        }

        private static byte[] GetEntropy(string salt)
        {
            return System.Text.Encoding.UTF8.GetBytes(salt);
        }

        private byte[] GetData()
        {
            return System.Text.Encoding.UTF8.GetBytes(String.Format("{0}%%%{1}", this.Token, this.ExpireDate.ToBinary()));
        }
    }
}
